﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Hanhud.Web.Publish
{
    public class CArticleCategory : ICategory<int, CArticleCategory>
    {
        #region Properties
        private int _articleCategoryID = -1;
        public int CategoryID
        {
            get { return _articleCategoryID; }
            private set { _articleCategoryID = value; }
        }

        private string _title = null;
        public string Title { get { return _title; } set { _title = value; } }

        private int _parentArticleCategoryID = -1;
        private ICategory<int, CArticleCategory> _parentCategory = null;
        public ICategory<int, CArticleCategory> ParentCategory
        {
            get
            {
                if (_parentArticleCategoryID > 0)
                {
                    if (_parentCategory == null)
                        _parentCategory = GetCategoryInfo(_parentArticleCategoryID);
                }
                return _parentCategory;
            }
            set
            {
                _parentCategory = value;
            }
        }

        private List<ICategory<int, CArticleCategory>> _childCategories = null;
        public List<ICategory<int, CArticleCategory>> ChildCategories
        {
            get
            {
                if (_childCategories == null)
                    _childCategories = new List<ICategory<int, CArticleCategory>>();
                return _childCategories;
            }
        }

        public string EncodedTitle
        {
            get { return _title; }
        }

        public CArticleCategory OfType
        {
            get { return this; }
        }

        private bool _private = false;
        public bool Private { get { return _private; } set { _private = value; } }

        private string _description = null;
        public string Description { get { return _description; } set { _description = value; } } 
        #endregion

        #region Constructors
        public CArticleCategory()
        {
        }

        public CArticleCategory(int articleCategoryID)
        {
            this.CategoryID = articleCategoryID;
        }

        public CArticleCategory(int articleCategoryID, int parentArticleCategoryID, string title, string description, bool bPrivate)
        {
            this.CategoryID = articleCategoryID;
            if (parentArticleCategoryID > 0)
            {
                _parentArticleCategoryID = parentArticleCategoryID;
                this.ParentCategory = new CArticleCategory(parentArticleCategoryID);
            }

            this.Title = title;
            this.Description = description;
            this.Private = bPrivate;
        } 
        #endregion

        public static CArticleCategory GetCategoryInfo(int articleCategoryID)
        {
            List<CArticleCategory> categoryTree = Data.Providers.CPublishProvider.Instance.GetCategoryInfo(articleCategoryID);
            CArticleCategory categoryInfo = categoryTree[0];
            categoryTree.RemoveAt(0);

            foreach (ICategory<int, CArticleCategory> cat in categoryTree)
            {
                if (cat.ParentCategory == categoryInfo)
                {
                    categoryInfo.ChildCategories.Add(cat);
                    cat.ParentCategory = categoryInfo;
                }
                else
                {
                    ICategory<int, CArticleCategory> parent = Find(categoryInfo.ChildCategories, cat.ParentCategory);
                    if (parent == null) throw new InvalidOperationException();

                    parent.ChildCategories.Add(cat);
                    cat.ParentCategory = parent;
                }
            }

            return categoryInfo;
        }

        public List<ICategory<int, CArticleCategory>> GetCategoryTree()
        {
            List<ICategory<int, CArticleCategory>> categoryTree = new List<ICategory<int, CArticleCategory>>();

            foreach (ICategory<int, CArticleCategory> category in Data.Providers.CPublishProvider.Instance.GetAllCategories())
            {
                if (category.OfType.ParentCategory == null)
                    categoryTree.Add(category);
                else
                {
                    ICategory<int, CArticleCategory> parent = Find(categoryTree, category.OfType.ParentCategory);
                    if (parent == null) throw new InvalidOperationException();

                    parent.ChildCategories.Add(category);
                    category.ParentCategory = parent;
                }
            }

            return categoryTree;
        }

        public static List<ICategory<int, CArticleCategory>> BuildTree()
        {
            List<ICategory<int, CArticleCategory>> categoryTree = new List<ICategory<int, CArticleCategory>>();

            foreach (ICategory<int, CArticleCategory> category in Data.Providers.CPublishProvider.Instance.GetAllCategories())
            {
                if (category.OfType.ParentCategory == null)
                    categoryTree.Add(category);
                else
                {
                    ICategory<int, CArticleCategory> parent = Find(categoryTree, category.OfType.ParentCategory);
                    if (parent == null) throw new InvalidOperationException();

                    parent.ChildCategories.Add(category);
                    category.ParentCategory = parent;
                }
            }

            return categoryTree;
        }

        private static ICategory<int, CArticleCategory> Find(List<ICategory<int, CArticleCategory>> categoryList, ICategory<int, CArticleCategory> match)
        {
            ICategory<int, CArticleCategory> foundCategory = null;

            foreach (ICategory<int, CArticleCategory> category in categoryList)
            {
                if (category.CategoryID == match.CategoryID)
                {
                    foundCategory = category;
                    break;
                }
                else if (category.ChildCategories != null && category.ChildCategories.Count > 0)
                {
                    if ((foundCategory = Find(category.ChildCategories, match)) != null)
                        break;
                }
            }

            return foundCategory;
        }
    }
}
